package net.jumpengine;

import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

import javafx.animation.AnimationTimer;
import javafx.geometry.VPos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import net.jumpengine.bean.Base;
import net.jumpengine.enume.GameState;
import net.jumpengine.event.ConfirmStateEvent;
import net.jumpengine.event.GameStateChangeEvent;
import net.jumpengine.inter.ILog;
import net.jumpengine.inter.IStateChangeEvent;
import net.jumpengine.inter.IStateEvent;
import net.jumpengine.inter.IUpdate;
import net.jumpengine.inter.IHandle;
import net.jumpengine.manager.BaseManager;
import net.jumpengine.manager.EventManager;
import net.jumpengine.manager.MusicManager;
import net.jumpengine.util.UComm;
import net.jumpengine.util.UIO;

/**
 * 游戏的总管理类, 有初始化游戏/游戏状态管理/事件/素材资源/音乐等
 * <br /><br />
 * <b>作者:&nbsp;</b>张天文 <br />
 * <b>日期:&nbsp;</b>2020-02-19 21:54<br />
 * @date
 */
public class Manager{
	private static Stage stage;
	private static volatile Enum<?> state,beforeState;
	
	private static Canvas can1,can2,current;
	private static GraphicsContext context;
	
	private static final EventManager eventManager=new EventManager();
	private static final BaseManager baseManager=new BaseManager();
	private static final MusicManager musicManager=new MusicManager();
	
	private static IStateChangeEvent stateChangeEvent=new GameStateChangeEvent();
	private static ILog log=new LogImpl();
	private static volatile AtomicBoolean autoAdd=new AtomicBoolean(true);
	
	private static Font font=new Font("宋体",12);
	private static Color backColor=Color.BLACK,color=Color.WHITE;
	private static AnimationTimer timer,animation;
	private static int fps,width,height;
	private static WritableImage snapshot;
	private static SnapshotParameters param=new SnapshotParameters ();
	
	private static ConfirmStateEvent confimStateEvent=new ConfirmStateEvent();

	private Manager() { 
		try {
			throw new Exception("net.jumpengine.Manager为静态类,不能初始化!");
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
	
	/**
	 * 游戏引擎初始化
	 * @param stage 窗体
	 * @param state 游戏状态
	 * @param width 窗体内容的高度,没有计算边框与标题的
	 * @param height 窗体内容的宽度
	 * @param fps 游戏每秒帧数,本引擎的帧数如果不修改的话,是固定的
	 */
	public static void init(Stage stage,Enum<?> state,int width,int height,int fps) {
		Manager.stage=stage;
		Manager.fps=fps;
		Manager.width=width;
		Manager.height=height;
		stage.setFullScreen(false);
		
		if(UComm.isNull(stage.getTitle()))stage.setTitle("JumpEngine v0.1 Test");
		if(UComm.isNull(stage.getIcons()))stage.getIcons().addAll(UIO.loadImages("/icon",Manager.class));
		
		can1=new Canvas(width,height);
		can2=new Canvas(width,height);
		snapshot=new WritableImage(width, height);
		Group group=new Group();
		group.getChildren().add(can1);
		group.getChildren().add(can2);
		Scene scene=new Scene(group,width,height);
		
		stage.setScene(scene);
		
		eventManager.init(group,scene);
		overturn();
		
		timer=new AnimationTimer() {
			private long time=System.currentTimeMillis(),snow;
			private List<Base> list;
			
			@Override
			public void handle(long now) {
				snow=System.currentTimeMillis();
				if (snow - time < 1000 / fps) {
                    try {
                        Thread.sleep(1000 / fps - (snow - time));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
				
				Manager.context=Manager.current.getGraphicsContext2D();
				Manager.context.setFont(Manager.font);
				Manager.context.setFill(Manager.backColor);
				Manager.context.fillRect(0, 0, Manager.width, Manager.height);
				Manager.context.setTextBaseline(VPos.TOP);
				Manager.context.setLineWidth(1);
				
				list = Manager.baseManager.currentSortList();
				if(list!=null) {
					for(Base base:list) {
						base.draw(Manager.context);
						Manager.context.setFont(Manager.font);
						Manager.context.setFill(Manager.backColor);
					}
					overturn();
				}
				time=snow;
			}
		};
		animation=new AnimationTimer() {
			private long time=System.currentTimeMillis(),snow;
			
			@Override
			public void handle(long now) {
				snow=System.currentTimeMillis();
				if (snow - time < 20) {
                    try {
                        Thread.sleep(20 - (snow - time));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
				
				List<IUpdate> list = Manager.baseManager.currentChangeList();
				if(list==null || list.size()==0)return;
				for(IUpdate inter:list) {
					if(inter.isAble())inter.update(now);		
				}
				
				time=snow;
			}
		};
		log.debug("manager[init]end");
		eventManager.addStateEvent(GameState.confirm, confimStateEvent);
		
		eventManager.initReady();
		
		setState(state);
				
		stage.show();
	}
	
	/** 翻转canvas */
	public static void overturn() {
		if(current==null || current==can2) {
			current=can1;
			can1.setVisible(true);
			can2.setVisible(false);
		}else {
			current=can2;
			can2.setVisible(true);
			can1.setVisible(false);
		}
	}

	/**
	 * 获取窗体对象
	 * @return 窗体对象
	 */
	public static Stage getStage() {
		return stage;
	}

	/**
	 * 获取当前的canvas
	 * @return 当前的canvas
	 */
	public static Canvas getCurrent() {
		return current;
	}

	/**
	 * 获取事件管理类
	 * @return 事件管理类
	 */
	public static EventManager getEventManager() {
		return eventManager;
	}

	/**
	 * 获取游戏状态
	 * @return 枚举
	 */
	public static Enum<?> getState() {
		return state;
	}

	/**
	 * 设置游戏状态
	 * @param state 游戏状态
	 */
	public static void setState(Enum<?> state) {
		setState(state,false);
	}
	
	/**
	 *  设置游戏状态
	 * @param state 游戏状态
	 * @param backImage 将当前画面截图, 作为新状态背景图
	 */
	public static void setState(Enum<?> state,boolean backImage) {
		beforeState=Manager.state;
		IStateEvent event = eventManager.currentStateEvent();
		if(event!=null)event.end();
		Manager.state=state;
		event = eventManager.currentStateEvent();
		if(!event.isLoaded())event.load();
		if(backImage) {
			current.snapshot(param, snapshot);
			event.setBackImage(snapshot);
		}
		event.show();
		stateChangeEvent.setStatus(beforeState, Manager.state);
	}
	
	/** 让游戏跳转至上一次的状态 */
	public static void beforeState() {
		Enum<?> e=beforeState;
		setState(e,false);
	}

	/**
	 * 获取全局字体
	 * @return 全局字体
	 */
	public static Font getFont() {
		return new Font(font.getFamily(),font.getSize());
	}
	
	/** 游戏的渲染与音乐开始 */
	public static void start() {
		timer.start();
		animation.start();
		musicManager.start();
	}
	
	/** 停止素材渲染和音乐播放 */
	public static void stop() {
		timer.stop();
		animation.stop();
		musicManager.stop();
	}

	/**
	 * 设置全局字体
	 * @param font 字体
	 */
	public static void setFont(Font font) {
		Manager.font = font;
	}

	/** 获取素材管理类 */
	public static BaseManager getBaseManager() {
		return baseManager;
	}
	
	/** 获取音乐管理类 */
	public static MusicManager getMusicmanager() {
		return musicManager;
	}

	/** 获取刷新频率 */
	public static int getFps() {
		return fps;
	}

	/**
	 * 设置刷新频率
	 * @param fps 大于0小于400的整数
	 */
	public static void setFps(int fps) {
		if(fps>0 && fps<400)Manager.fps = fps;
	}

	/** 获取游戏状态更改事件处理类 */
	public static IStateChangeEvent getStateChangeEvent() {
		return stateChangeEvent;
	}

	/**
	 * 设置游戏状态更改事件处理类
	 * @param stateEvent 游戏状态更改事件处理类
	 */
	public static void setStateEvent(IStateChangeEvent stateEvent) {
		Manager.stateChangeEvent = stateEvent;
	}

	/** 获取全局背景色 */
	public static Color getBackColor() {
		return backColor;
	}

	/**
	 * 设置全局背景色,每个Base绘制完成后,Fill都会重置成此颜色
	 * @param color 全局背景色
	 */
	public static void setBackColor(Color color) {
		Manager.backColor = color;
	}

	/** 获取全局日志 */
	public static ILog getLog() {
		return log;
	}

	/**
	 * 设置全局日志
	 * @param log 日志处理类
	 */
	public static void setLog(ILog log) {
		Manager.log = log;
	}	
	
	/**
	 * 获取除去边框外显示区域宽度
	 * @return 显示区域宽度
	 */
	public static int getHeight() {
		return height;
	}

	/**
	 * 获取除去边框外显示区域高度
	 * @return 显示区域高度
	 */
	public static int getWidth() {
		return width;
	}

	/**
	 * 获取全局前景色,一般为字体颜色
	 * @return 全局前景色
	 */
	public static Color getColor() {
		return color;
	}

	/**
	 * 设置全局前景色,一般为字体颜色
	 * @param color
	 */
	public static void setColor(Color color) {
		Manager.color = color;
	}
	
	public static void confirm(String message,IHandle handle) {
		confirm(message,"操  作  确  认",handle);
	}
	public static void confirm(String message,String title,IHandle handle) {
		confimStateEvent.set(title, message, handle);
		setState(GameState.confirm);
	}

	/**
	 * 获取BaseManager是否自动添加素材
	 * @return true,每个继承Base类都会自动添加至当前State的素材集合中
	 */
	public static boolean getAutoAdd() {
		return autoAdd.get();
	}

	/**
	 * 设置BaseManager是否自动添加素材
	 * @param autoAdd 默认true,每个继承Base类都会自动添加至当前State的素材集合中.False关闭, 用于加载页面
	 */
	public static void setAutoAdd(boolean autoAdd) {
		Manager.autoAdd .set(autoAdd);
	}
}
